/**音乐、声音管理
 * 支持多个声音播放，可独立设置每个声音的音量、循环次数、偏移量。
 * 声音可以分组播放、静音和恢复
 * */
package utils.media
{
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.media.SoundTransform;
	import flash.net.URLRequest;
	import flash.utils.Dictionary;
	public class MultiSound
	{
		private static var soundDic:Dictionary = new Dictionary();//已播放过的声音字典
		private static var soundChannelDic:Dictionary = new Dictionary();//声音播放声道
		private static var soundPara:Dictionary = new Dictionary();//声音播放参数，每个元素是声音的play()方法参数数组
		private static var soundGroup:Dictionary = new Dictionary();//声音组参数，每个元素是一个存放相同组的声音名称的数组 
		private static var silenceSoundDic:Dictionary = new Dictionary();//已经被静音的声音组
		
		
		public static var version:String="";//版本号
				
		public function MultiSound()
		{
			
		}
		
		/**播放声音
		 * @param url：声音文件完整地址
		 * @param repeatTime：0为不循环，-1为无限循环
		 * @param name：如果不为null，则从字典中找到对应的Sound对象，找不到则使用新Sound独立播放
		 * @param channel: 此次播放声道的外部引用
		 * @param volum: 播放的音量(0到1)
		 * */
		public static function play(url:String,repeatTime:int=0,name:String=null,volum:Number=1,groupName:String=null):void
		{
			var sound:Sound;
			var soundChannel:SoundChannel;
			var urlreq:URLRequest = new URLRequest(url+MultiSound.version);
			var soundTransform:SoundTransform = new SoundTransform(volum);
			if(name == null)
				name = url;
			if(name != null)
			{
				
				sound = MultiSound.soundDic[name];
				
				if(sound != null)
				{
					soundChannel = (MultiSound.soundChannelDic[name] as SoundChannel);
					if(soundChannel != null)
						soundChannel.stop();
					if(repeatTime == -1)
					{
						if(sound.url)
						{
							MultiSound.soundPara[name] = [0,int.MAX_VALUE,soundTransform];
							try
							{
								MultiSound.soundChannelDic[name] = sound.play(0,int.MAX_VALUE,soundTransform);
							}
							catch(e:Error)
							{
								trace(e.message);
							}
						}
						else
						{
							sound.addEventListener(IOErrorEvent.IO_ERROR,onIOError);
							sound.addEventListener(Event.COMPLETE,onSoundLoadComplete,false,0,true);
							sound.load(urlreq);
						}
					}
					else
					{
						MultiSound.soundPara[name] = [0,repeatTime,soundTransform];
						try{
							MultiSound.soundChannelDic[name] = sound.play(0,repeatTime,soundTransform);
						}
						catch(e:Error)
						{
							trace(e.message);
						}
					}
				}
				else
				{
					sound = new Sound();
					sound.addEventListener(IOErrorEvent.IO_ERROR,onIOError)//,false,0,true);
					sound.addEventListener(Event.COMPLETE,onSoundLoadComplete)//,false,0,true);
					MultiSound.soundDic[name] = sound;
					sound.load(urlreq);
				}
				if(groupName != null)
				{
					if(soundGroup[groupName] == null)
						soundGroup[groupName] = new Array();
					if(soundGroup[groupName].indexOf(name) == -1)
					{
						soundGroup[groupName] = new Array();             //add by 刘习堂 
						
					}
					soundGroup[groupName].push(name);
				}
			}
			
			function onSoundLoadComplete(evt:Event):void
			{
				if(repeatTime == -1)
				{
					sound.removeEventListener(IOErrorEvent.IO_ERROR,onIOError);
					sound.removeEventListener(Event.COMPLETE,onSoundLoadComplete);
					//sound.addEventListener(Event.SOUND_COMPLETE,FunctionFactory.Create(replay,sound,channel));
					MultiSound.soundPara[name] = [0,int.MAX_VALUE,soundTransform];
					MultiSound.soundChannelDic[name] = sound.play(0,int.MAX_VALUE,soundTransform);
				}
				else
				{
					MultiSound.soundPara[name] = [0,repeatTime,soundTransform];
					MultiSound.soundChannelDic[name] = sound.play(0,repeatTime,soundTransform);
				}
			}
			
		}
		
		private static function onIOError(e:IOErrorEvent):void
		{
			trace("找不到声音文件: " + e.text);
			var sound:Sound = e.currentTarget as Sound;
			sound.removeEventListener(IOErrorEvent.IO_ERROR,onIOError);
		}
		
		private static function replay(sound:Sound,channel:SoundChannel):void
		{
			channel = sound.play(0,int.MAX_VALUE);
		}
		
		/**播放字典中已经存在的声音
		 * @param soundName:声音名
		 * */
		 public static function playExistSound(soundName:String):Boolean
		 {
			 var soundTransform:SoundTransform = new SoundTransform(1);
		 	var channel:SoundChannel = MultiSound.soundChannelDic[soundName];
		 	var sound:Sound = MultiSound.soundDic[soundName];
		 	if(channel != null)
		 	{
				
		 		channel.stop();
		 		var param:Array = MultiSound.soundPara[soundName]
		 		if(sound != null)
		 		{
		 			MultiSound.soundChannelDic[soundName] = sound.play(param[0],param[1],soundTransform);  //刘习堂改param[1]为soundTransform
		 			return true;
		 		}
		 	}
		 	return false;
		 }
		
		/**改变字典中某个声音的音量
		 * @param soundName:字典中的声音名称
		 * @param volume:音量。0 到 1
		 * */
		public static function setSoundVolume(soundName:String,volume:Number=1):void
		{
			var soundChannel:SoundChannel = MultiSound.soundChannelDic[soundName];
			if(soundChannel != null) 
			{
				var st:SoundTransform = soundChannel.soundTransform;
				st.volume = volume;
				soundChannel.soundTransform = st;
			}
		}
		
		/**停止某个声音
		 * @param soundName:字典中的声音名称
		 * @param clearMemory:是否同时卸载声音资源
		 * */
		public static function stopSound(soundName:String,clearMemory:Boolean=false):void
		{
			var sound:Sound = MultiSound.soundDic[soundName] as Sound;
			if(sound != null)
			{
				try{sound.close();}
				catch(e:Error)
				{
					trace(e.message);
				}
				
			}
			var soundChannel:SoundChannel = MultiSound.soundChannelDic[soundName];
			if(soundChannel != null)
			{
				soundChannel.stop();
				soundChannel = null;
			}
			if(clearMemory)
			{
				clearSound(soundName);
			}
		}
		
		/**卸载某个声音资源
		 * @param soundName:字典中的声音名称
		 * */
		public static function clearSound(soundName:String):void
		{
			var soundChannel:SoundChannel = MultiSound.soundChannelDic[soundName];
			if(soundChannel != null)
			{
				soundChannel.stop();
				delete MultiSound.soundChannelDic[soundName];
				soundChannel = null;
			}
			var sound:Sound = MultiSound.soundDic[soundName] as Sound;
			if(sound != null)
			{
				try{sound.close();}
				catch(e:Error)
				{
					trace(e.message)
				}
				sound = null;
				delete MultiSound.soundDic[soundName];
			}
			
		}
		
		/**销毁声音组
		 * @param groupName:声音组名
		 * @param clearSound:是否同时将该声音组中的声音卸载掉
		 * 销毁声音组后将无法每个声音的具体播放参数，如果需要关闭后再恢复播放（保持参数不变），
		 * 请使用silenceGroup(),
		 * */
		public static function destroyGroup(groupName:String):void
		{
			var soundNames:Array = soundGroup[groupName];
			if(soundNames == null)
				return;
			var soundName:String;
			for each(soundName in soundNames)
			{
				MultiSound.clearSound(soundName);
			}
			soundNames.length = 0;
			delete soundGroup[groupName];
			
		}
		
		/**使声音组静音
		 * @param groupName:声音组名
		 * */
		public static function silenceGroup(groupName:String):void
		{
			var soundNames:Array = soundGroup[groupName];
			if(soundNames == null)
				return;
			var soundName:String;
			for each(soundName in soundNames)
			{
				MultiSound.setSoundVolume(soundName,0);
			}
		}
		
		/**打开某个声音组中的声音
		 * @param groupName:声音组名
		 * */
		public static function playGroup(groupName:String):void
		{
			var soundNames:Array = soundGroup[groupName];
			if(soundNames == null)
				return;
			var soundName:String;
			for each(soundName in soundNames)
			{
				MultiSound.playExistSound(soundName);
			}
		}
		

	}
}